// 文件路径: dbms/DbmsServer.java
package com.dbms;

import com.dbms.cluster.ClusterManager;
import com.dbms.cluster.NodeInfo;
import com.dbms.cluster.PeerNodeHandler;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 数据库服务器主程序，负责：
 * 1. 启动数据库核心服务（DbmsCore）
 * 2. 监听客户端连接并处理请求
 * 3. 集群模式下启动节点间通信监听，支持节点协作
 *
 * 【已修改】支持两种运行模式：
 * - 单机模式：独立运行，不参与集群
 * - 集群模式：作为集群节点启动，每个节点使用独立的数据库文件，支持节点间通信
 */
public class DbmsServer {
    // 默认客户端连接端口（单机模式使用）
    private static final int DEFAULT_CLIENT_PORT = 9999;
    // 数据库核心组件实例，封装数据存储、事务、SQL执行等核心功能
    private final DbmsCore dbmsCore;
    // 线程池：用于并发处理客户端连接和节点间通信，提高服务器吞吐量
    private final ExecutorService threadPool = Executors.newCachedThreadPool();
    // 集群节点ID：null表示单机模式，非null表示集群中的节点标识（如"node1"）
    private final String nodeId;

    /**
     * 构造方法：初始化数据库服务器
     * @param nodeId 集群节点ID（null=单机模式，非null=集群模式）
     */
    public DbmsServer(String nodeId) {
        this.nodeId = nodeId;
        // 集群模式初始化：节点ID非空时，初始化集群管理器
        if (this.nodeId != null) {
            System.out.println("Initializing DBMS Core for Cluster Node '" + nodeId + "'...");
            ClusterManager.getInstance(nodeId); // 初始化集群管理器，注册当前节点
        } else {
            // 单机模式初始化
            System.out.println("Initializing DBMS Core for Standalone Server...");
        }

        // 【核心修改】将节点ID传入DbmsCore，实现每个集群节点使用独立的数据库文件
        // 集群模式下文件名为"nodeId.db"（如node1.db），单机模式使用默认文件名
        this.dbmsCore = new DbmsCore(nodeId);
        System.out.println("DBMS Core initialized successfully.");
    }

    /**
     * 启动服务器：监听客户端连接，集群模式下同时启动节点间通信监听
     * @throws IOException 端口占用或网络异常时抛出
     */
    public void start() throws IOException {
        // 确定客户端监听端口：集群模式使用节点配置的端口，单机模式使用默认端口
        int clientPort = DEFAULT_CLIENT_PORT;
        if (this.nodeId != null) {
            // 集群模式：启动节点间通信监听器（处理其他节点的请求）
            startInterNodeListener();
            // 从集群配置中获取当前节点的客户端端口
            clientPort = ClusterManager.getInstance().getSelfNode().getClientPort();
        }

        // 启动客户端连接监听器
        ServerSocket serverSocket = new ServerSocket(clientPort);
        System.out.println("DBMS Server started on port " + clientPort + ". Waiting for clients...");

        // 循环接受客户端连接（服务器主循环）
        while (true) {
            // 阻塞等待客户端连接
            Socket clientSocket = serverSocket.accept();
            System.out.println("Client connected from: " + clientSocket.getInetAddress());
            // 将客户端连接提交给线程池处理（使用ClientHandler）
            threadPool.submit(new ClientHandler(clientSocket, dbmsCore));
        }
    }

    /**
     * 启动集群节点间通信监听器（仅集群模式）
     * 功能：监听其他集群节点的连接请求，处理节点间数据同步、请求转发等
     */
    private void startInterNodeListener() {
        // 获取当前节点的信息（包含节点间通信端口）
        NodeInfo selfNode = ClusterManager.getInstance().getSelfNode();
        int interNodePort = selfNode.getPort();

        // 在独立线程中启动节点间通信服务（避免阻塞客户端监听）
        new Thread(() -> {
            try (ServerSocket interNodeServerSocket = new ServerSocket(interNodePort)) {
                System.out.println("Cluster communication listener started on port " + interNodePort +
                        " for node '" + selfNode.getNodeId() + "'.");
                // 循环接受其他节点的连接
                while (true) {
                    Socket peerNodeSocket = interNodeServerSocket.accept();
                    System.out.println("Accepted connection from peer node: " + peerNodeSocket.getInetAddress());
                    // 将节点间连接提交给线程池处理（使用PeerNodeHandler）
                    threadPool.submit(new PeerNodeHandler(peerNodeSocket, dbmsCore));
                }
            } catch (IOException e) {
                System.err.println("FATAL: Failed to start inter-node listener for node '" + selfNode.getNodeId() + "': " + e.getMessage());
                e.printStackTrace();
            }
        }).start();
    }

    /**
     * 程序入口：启动数据库服务器
     * @param args 命令行参数，第一个参数为节点ID（可选，集群模式使用）
     */
    public static void main(String[] args) {
        try {
            // 解析命令行参数：获取节点ID（单机模式为null）
            String nodeId = null;
            if (args.length > 0) {
                nodeId = args[0];
            }
            // 创建并启动服务器
            DbmsServer server = new DbmsServer(nodeId);
            server.start();
        } catch (IOException e) {
            // 处理启动失败（如端口被占用）
            System.err.println("FATAL: Failed to start server: " + e.getMessage());
            e.printStackTrace();
        }
    }
}